#include "Protocol.h"
#include "CrcUtility.h"
#include "Uart.h"

Protocol::Protocol()
{
}

Protocol* Protocol::getInstance()
{
    static Protocol singleton{};
    return &singleton;
}


void Protocol::parse(uint8_t* buffer)
{
    static Frame frame;
    uint8_t calculateCrc = 0;

    if (buffer[0] != FRAME_HEADER) {
        frame.state = FRAME_STATE_NOT_FIND_HEAD;
        return;
    }

    frame.head = FRAME_HEADER;
    frame.from = buffer[1];
    frame.from = frame.from << 8 | buffer[2];
    frame.to = buffer[3];
    frame.to = frame.to << 8 | buffer[4];
    frame.commandCode = buffer[5];
    frame.commandCode = frame.commandCode << 8 | buffer[6];
    frame.datalLength = buffer[7];
    frame.datalLength = frame.datalLength << 8 | buffer[8];
    frame.reserved01 = buffer[9];
    frame.reserved02 = buffer[10];
    frame.reserved03 = buffer[11];
    frame.data = &buffer[12];
    frame.crc = buffer[frame.datalLength + 12];

    calculateCrc = CrcUtility::getInstance()->calculateCrc8(&buffer[1], 11 + frame.datalLength);
    if (frame.crc != calculateCrc) {
        frame.state = FRAME_STATE_CRC_ERROR;
//        return;
    }
    frame.state = FRAME_STATE_COMPLETE;
    emit parseCompleteSignal(&frame);
}

void Protocol::send(Frame* frame)
{
    static uint8_t buffer[FRAME_MAX_LENGTH] = {0};

    buffer[0] = FRAME_HEADER;
    buffer[1] = frame->from >> 8 & 0xff;
    buffer[2] = frame->from & 0xff;
    buffer[3] = frame->to >> 8 & 0xff;
    buffer[4] = frame->to & 0xff;
    buffer[5] = frame->commandCode >> 8 & 0xff;
    buffer[6] = frame->commandCode & 0xff;
    buffer[7] = frame->datalLength >> 8 & 0xff;
    buffer[8] = frame->datalLength & 0xff;
    buffer[9] = 0x00;//reserved
    buffer[10] = 0x00;//reserved
    buffer[11] = 0x00;//reserved

    for (int16_t i = 0; i < frame->datalLength; i++) {
        buffer[12 + i] = frame->data[i];
    }
    buffer[12 + frame->datalLength] = CrcUtility::getInstance()->calculateCrc8(&buffer[1], 11 + frame->datalLength);
    buffer[13 + frame->datalLength] = FRAME_TAIL;
    Uart::getInstance()->sendData(buffer, frame->datalLength + 14);
}
